
const axios = require("axios");
const puppeteer = require("puppeteer-extra");
const StealthPlugin = require("puppeteer-extra-plugin-stealth");
puppeteer.use(StealthPlugin());
const readline = require("readline");
const url = require("url");
const dayjs = require("dayjs");
const { sendWechatMessage } = require("../../utils");
const md5 = require("md5");
const { extractImageUrl } = require("../../utils");

const logger = require("../../utils/logger");
const notification = require("../../utils/notification");

const executablePath = process.env.WEB_CONFIG_EXECUTABLE_PATH;
const userDataDir = process.env.WEB_CONFIG_USER_DATA_DIR;

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

exports.handleCommand = async (command, params) => {
  switch (command) {
    case "getArticlesInfo":
      const data = await getArticlesInfo(params);
      return { data };
    case "getUserInfo":
      return await getUserInfo(params.userId);
    default:
      throw new Error("Unsupported command");
  }
};

//获取公众号图文消息数据

const getArticlesInfo = async (params) => {
  const browser = await puppeteer.launch({
    headless: false,
    headless: "new",
    userDataDir,
    executablePath,
    args: [
      "--no-sandbox",
      "--disable-setuid-sandbox",
      "--disable-features=site-per-process",
    ],
    ignoreHTTPSErrors: true,
  });

  try {
    const page = await browser.newPage();
    // 登录
    await page.goto("https://mp.weixin.qq.com/?token=&lang=zh_CN");

    async function isNotLogin(page) {
      try {
        return await page.evaluate(() => {
          const element = document.querySelector(".weui-desktop-global__info");
          return element ? element.innerText.includes("登录") : false;
        });
      } catch (error) {
        if (error.message.includes("Execution context was destroyed")) {
          return false;
        }
        throw error;
      }
    }

    async function waitForUserLogin(page) {
      return new Promise((resolve, reject) => {
        logger.info("请在浏览器中完成登录，登录成功后脚本将自动继续...");
        let qrCodeRefreshCount = 0;
        const maxRefreshAttempts = 5;
        const checkInterval = setInterval(async () => {
          try {
            const notLoggedIn = await isNotLogin(page);
            if (!notLoggedIn) {
              clearInterval(checkInterval);
              clearTimeout(timeoutId);
              logger.info("检测到登录成功");
              resolve();
            } else {
              // #TAG:
              // 2024年9月14日，微信公众号二维码过期时间超过10分钟，暂时可以不用检查二维码是否过期
              // const isQRCodeExpired = await page.evaluate(() => {
              //   const expiredText = document.querySelector(
              //     ".weui-desktop-qrcode__refresh"
              //   );
              //   return expiredText && expiredText.style.display !== "none";
              // });
              // if (isQRCodeExpired && qrCodeRefreshCount < maxRefreshAttempts) {
              //   logger.info("二维码已过期，正在刷新...");
              //   await refreshQRCode(page);
              //   qrCodeRefreshCount++;
              // }
            }
          } catch (error) {
            logger.error(`检查登录状态时出错:${error}`);
          }
        }, 2000); // 每2秒检查一次

        // 设置10分钟超时
        const timeoutId = setTimeout(async () => {
          clearInterval(checkInterval);
          logger.error("登录等待超时（10分钟）");
          await notification(
            "微信公众号",
            `${process.env.NODE_ENV}环境下的微信公众号登录失败`,
            "等待超时"
          );
          reject(new Error("登录等待超时，请重试"));
        }, 10 * 60 * 1000); // 10分钟
      });
    }

    async function refreshQRCode(page) {
      await page.evaluate(() => {
        const refreshButton = document.querySelector(
          ".weui-desktop-qrcode__refresh"
        );
        if (refreshButton) {
          refreshButton.click();
        }
      });
      await notification(
        "微信公众号",
        `${process.env.NODE_ENV}环境下的微信公众号登录二维码已过期`,
        "正在刷新"
      );
      await new Promise((resolve) => setTimeout(resolve, 3000)); // 等待新二维码加载

      await getAndSendQRCode(page);
    }

    async function getAndSendQRCode(page) {
      try {
        const imgData = await page.evaluate(async () => {
          const img = document.querySelector(
            ".login__type__container__scan__qrcode"
          );
          if (!img) return null;

          const response = await fetch(img.src);
          const blob = await response.blob();
          return new Promise((resolve) => {
            const reader = new FileReader();
            reader.onloadend = () => resolve(reader.result);
            reader.readAsDataURL(blob);
          });
        });

        if (imgData) {
          logger.info("成功获取二维码图片数据");
          const base64Data = imgData.split(",")[1];
          const imgBuffer = Buffer.from(base64Data, "base64");

          await sendWechatMessage({
            msgtype: "image",
            image: {
              base64: base64Data,
              md5: md5(imgBuffer),
            },
          });
          logger.info("二维码图片已成功发送");
        } else {
          logger.error("无法获取新的二维码图片");
          throw new Error("无法获取新的二维码图片");
        }
      } catch (error) {
        logger.error(`获取或发送二维码时发生错误: ${error.message}`);
        await notification(
          "微信公众号",
          `${process.env.NODE_ENV}环境下的微信公众号登录二维码获取失败`,
          error.message
        );
      }
    }

    if (await isNotLogin(page)) {
      // 等待登录
      logger.error("请先登录微信公众平台，并刷新页面");
      await notification(
        "微信公众号",
        `${process.env.NODE_ENV}环境的微信公众号数据获取失败`,
        "请重新登录"
      );
      await getAndSendQRCode(page);
      await waitForUserLogin(page);
      await notification(
        "微信公众号",
        `${process.env.NODE_ENV}环境的微信公众号登录成功`,
        "登录成功"
      );
    }
    logger.info("已登录");
    // 打印一下当前的URL
    const currentUrl = await page.url();
    logger.info(currentUrl);

    const parsedUrl = new url.URL(currentUrl);
    // 获取 token 的值
    const token = parsedUrl.searchParams.get("token");

    // 根据传入的参数确定日期范围
    let startDate;
    if (params.update_type === "highFrequency") {
      startDate = dayjs().subtract(7, "day");
    } else if (params.interval) {
      const days = parseInt(params.interval);
      startDate = dayjs().subtract(days, "day");
    } else {
      // 默认获取最近30天的数据
      startDate = dayjs().subtract(30, "day");
    }

    // 跳转内容与互动/发表记录页面
    const listPageUrl = `https://mp.weixin.qq.com/cgi-bin/appmsgpublish?sub=list&begin=0&count=10&token=${token}&lang=zh_CN`;
    await page.goto(listPageUrl);

    let allData = [];
    //如果存在这个元素，说明没有数据
    try {
      await page.waitForSelector(".publish-list__empty");
      logger.info("没有数据");
      return [];
    } catch (error) {
      logger.info("有数据");
    }
    let hasNextPage = true;
    let pageIndex = 0;

    while (hasNextPage) {
      await page.waitForSelector(".publish_hover_content");

      // 获取当前页面上所有文章的详情按钮
      const detailButtons = await page.$$(
        ".weui-desktop-icon.weui-desktop-icon__rate.weui-desktop-icon__small.weui-desktop-icon_color"
      );
      const article_titles = await page.$$("a.weui-desktop-mass-appmsg__title");
      for (let i = 0; i < detailButtons.length; i++) {
        // 获取当前文章的 publish_hover_content div
        const hoverContent = await page.evaluateHandle((index) => {
          return document.querySelectorAll(".publish_hover_content")[index];
        }, i);
        // 获取状态文本
        let statusText = "";
        if (hoverContent) {
          statusText = await page.evaluate(
            (el) => el.parentElement.querySelector('.weui-desktop-mass__status_text').textContent.trim(),
            hoverContent
          );
        }

        // 检查文章态
        if (!statusText.includes("已发表") && !statusText.includes("已群发")) {
          logger.info(`跳过未发表的文章: ${statusText}`);
          continue; // 跳到下一个文章
        }
        // 尝试点击详情按钮
        const newPagePromise = new Promise((resolve) =>
          browser.once("targetcreated", (target) => resolve(target.page()))
        );
        await new Promise((resolve) => setTimeout(resolve, 1500));
        await detailButtons[i].click();
        let newPage;
        try {
          newPage = await Promise.race([
            newPagePromise,
            new Promise((_, reject) =>
              setTimeout(() => reject(new Error("Timeout")), 3000)
            ),
          ]);
        } catch (error) {
          // 如果没有新页面打开，说明是今天刚发布的文章
          logger.info("检测到今天发布的文章，从列表页面获取数据");
          const todayArticleInfo = await page.evaluate((content) => {
            const getTextContent = (selector) => {
              const element = content.querySelector(selector);
              return element ? element.textContent.trim() : "";
            };

            return {
              title: getTextContent(".weui-desktop-mass-appmsg__title span"),
              detail_url: content
                .querySelector(".weui-desktop-mass-appmsg__title")
                .getAttribute("href"),
              publish_time: new Date().toISOString().split("T")[0], // 使用今天的日期
              //获取元素style里面的background-image
              cover:
                content.querySelector(".weui-desktop-mass-appmsg__thumb")?.style
                  .backgroundImage || "",
              read_count: Number(
                getTextContent(
                  ".weui-desktop-tooltip__wrp:nth-child(1) .weui-desktop-mass-media__data__inner"
                ).replace(/,/g, "")
              ),
              avg_stay_time: 0,
              complete_read_rate: "0%",
              follow_after_read: 0,
              share_count: 0,
              like_count: Number(
                getTextContent(
                  ".weui-desktop-tooltip__wrp:nth-child(2) .weui-desktop-mass-media__data__inner"
                )
              ),
              favor_count: Number(
                getTextContent(
                  ".weui-desktop-tooltip__wrp:nth-child(3) .weui-desktop-mass-media__data__inner"
                )
              ),
              reward_amount: 0,
              comment_count: Number(
                getTextContent(
                  ".weui-desktop-tooltip__wrp:nth-child(4) .weui-desktop-mass-media__data__inner"
                )
              ),
            };
          }, hoverContent);
          todayArticleInfo.publish_time = dayjs(
            todayArticleInfo.publish_time
          ).format("YYYY-MM-DD HH:mm:ss");
          todayArticleInfo.cover = extractImageUrl(todayArticleInfo.cover);
          todayArticleInfo.crawl_time = dayjs().format("YYYY-MM-DD HH:mm:ss");
          const parsedUrl = url.parse(todayArticleInfo.detail_url, true);
          const queryParams = parsedUrl.query;
          todayArticleInfo.mid = queryParams.mid;
          todayArticleInfo.idx = queryParams.idx;
          todayArticleInfo.cover = JSON.stringify([todayArticleInfo.cover]);
          allData.push(todayArticleInfo);
          logger.info(
            `抓取到今天发布的文章: ${todayArticleInfo.publish_time} - ${todayArticleInfo.title}`
          );
          continue; // 继续处理下一篇文章
        }
        try {
          await newPage.waitForSelector(".article_info", { timeout: 5000 });
        } catch (error) {
          logger.info(`页面加载超时或未找到 .article_info 元素，结束抓取过程`);
          await newPage.close();
          hasNextPage = false;
          break; // 跳出 for 循环
        }

        // 获取详细信息，包括发布日期
        const detailInfo = await newPage.evaluate(async () => {
          await new Promise((resolve) => setTimeout(resolve, 1500));
          const getTextContent = (selector) => {
            const element = document.querySelector(selector);
            return element ? element.textContent.trim() : "";
          };

          const getNumericValue = (selector) => {
            const text = getTextContent(selector);
            return text || 0;
          };
          const getAllElements = (selector) => {
            return document.querySelectorAll(selector);
          };

          return {
            title: getTextContent(".article_title"), //标题
            publish_time: getTextContent(".article_desc span:first-child"), //发布日期
            cover: document.querySelector(".article_cover")?.src || "", //封面
            read_count: Number(
              getAllElements(".bottom_data_tips")[0]
                .querySelector(".tips_val_num")
                .textContent.trim()
                .replace(/,/g, "")
            ), //阅读
            avg_stay_time: Number(
              getAllElements(".bottom_data_tips")[1]
                .querySelector(".tips_val_num")
                .textContent.trim()
            ), //平均停留时间
            complete_read_rate: getAllElements(".bottom_data_tips")[2]
              .querySelector(".tips_val_num")
              .textContent.trim(), //完成阅读率
            follow_after_read: +getAllElements(".bottom_data_tips")[3]
              .querySelector(".tips_val_num")
              .textContent.trim(), //阅读后关注
            share_count: +getNumericValue(".data_list:nth-child(2) .data_num"), //分享数
            favor_count: +getNumericValue(".data_list:nth-child(3) .data_num"), //在看
            like_count: +getNumericValue(".data_list:nth-child(4) .data_num"), //点赞
            reward_amount: +getNumericValue(
              ".data_list:nth-child(5) .data_num"
            ), //赞赏
            comment_count: +getNumericValue(
              ".data_list:nth-child(6) .data_num"
            ), //留言
          };
        });
        // 解析并检查发布日期
        const publish_time = dayjs(detailInfo.publish_time, "YYYY/MM/DD");

        if (publish_time.isBefore(startDate)) {
          await newPage.close();
          hasNextPage = false;
          break;
        }
        detailInfo.publish_time = dayjs(detailInfo.publish_time).format(
          "YYYY-MM-DD HH:mm:ss"
        );
        detailInfo.crawl_time = dayjs().format("YYYY-MM-DD HH:mm:ss");
        // 获取状态文本
        let detail_url = "";
        if (article_titles[i]) {
          detail_url = await page.evaluate(
            (el) => el.getAttribute("href") || "",
            article_titles[i]
          );
        }
        detailInfo.detail_url = detail_url; //图文详情链接
        detailInfo.cover = JSON.stringify([detailInfo.cover]);
        const parseUrl = url.parse(detailInfo.detail_url, true);
        const queryParams = parseUrl.query;
        detailInfo.mid = queryParams.mid;
        detailInfo.idx = queryParams.idx;
        logger.info(
          `抓取到文章: ${detailInfo.publish_time} - ${detailInfo.title}`
        );
        allData.push(detailInfo);

        await new Promise((resolve) => setTimeout(resolve, 3000));
        // 关闭详情页标签
        await newPage.close();
      }

      if (hasNextPage) {
        // 查找所有分页按钮
        const pageButtons = await page.$$(
          ".weui-desktop-btn.weui-desktop-btn_default.weui-desktop-btn_mini"
        );
        // 找到"下一页"按钮
        const nextButton = await page.evaluateHandle(() => {
          const buttons = Array.from(
            document.querySelectorAll(
              ".weui-desktop-btn.weui-desktop-btn_default.weui-desktop-btn_mini"
            )
          );
          return buttons.find(
            (button) => button.textContent.trim() === "下一页"
          );
        });

        if (nextButton && nextButton?.click) {
          logger.info("正准备点击下一页按钮");
          await nextButton?.click();
          await page.waitForNavigation({ waitUntil: "networkidle0" });
          pageIndex++;
        } else {
          hasNextPage = false;
          logger.info("没有下一页按钮，结束循环");
        }
      }
    }

    logger.info(`获取到 ${allData.length} 条数据`);
    return allData;
  } catch (err) {
    logger.error(`发生错误: ${err.message}`);
    return []; // 发生错误时返回空数组
  } finally {
    await browser.close(); // 确保浏览器被关闭
  }
};

const getUserInfo = async (userId) => {
  // 实现获取用户信息功能
  const response = await axios.get(`https://api.wechat.com/user/${userId}`);
  return response.data;
};
